Skip to content

feat(tree): flavoured memory trees — ask-driven distillation into a ≤1000-token root markdown artifact#70

Merged
senamakel merged 2 commits into
mainfrom
feat/flavoured-trees
Jul 14, 2026
Merged

feat(tree): flavoured memory trees — ask-driven distillation into a ≤1000-token root markdown artifact#70
senamakel merged 2 commits into
mainfrom
feat/flavoured-trees

Conversation

@senamakel

Copy link
Copy Markdown
Member

Closes #68.

Summary

Adds a new flavoured tree kind: a variant of the source/topic/global bucket-seal trees that is instantiated with a specific ask/flavour (e.g. "tweet writing style", "coding preferences") and continuously distills everything ingested into it through that lens. The top of the tree compiles into a single, always-fresh markdown file (≤1000 tokens by default) a host can drop verbatim into a prompt as a style/preference profile.

Built entirely on the existing bucket-seal SQLite tree engine (src/memory/tree/) — same seal-and-cascade machinery, but every summarisation step is steered by the ask, and the root has a first-class compiled artifact.

Changes

  1. Tree kindTreeKind::Flavoured ("flavoured" wire string), SummaryTreeKind::Flavoured with wiki/summaries/flavoured-<scope>/ path routing + front-matter, and every match tree.kind site updated.
  2. Persisted ask — nullable mem_tree_trees.ask column (schema + idempotent add_column_if_missing migration), Tree.ask: Option<String> threaded through insert / row_to_tree / every SELECT. get_or_create_tree_with_ask stamps it at create time.
  3. Steered summarisationSummaryContext.ask, populated from the tree row at seal; prepare_summary_prompt emits a flavour-directed profile prompt when an ask is present. No LLM coupling — the ask just rides along in the context; ConcatSummariser stays the deterministic fallback.
  4. FactoryTreeFactory::flavoured(scope, ask) with LabelStrategy::Empty.
  5. Compiled root (the deliverable)compile_flavoured_root(config, tree_id) -> Result<String>: reads the root SummaryNode body, clamps to flavour_root_token_budget tokens, and stages it atomically (overwritten in place) at a stable flavoured/<scope>.md with YAML front-matter (ask, tree id, scope, sealed_at, leaves_folded evidence changelog, token estimate). Recompiled after any seal that touches the root via a hook in cascade_all_from_with_services (covers append_leaf, flush, and force_flush_tree/seal_now).
  6. ConfigTreeConfig::flavour_root_token_budget (default 1000).
  7. Docs — spec page docs/spec/flavoured-trees.md (contract, wire strings, artifact format).
  8. Tests — unit tests for compile_flavoured_root (staging, budget clamp, non-flavoured rejection, auto-recompile) and an end-to-end integration test tests/flavoured_tree.rs.

Testing

  • cargo fmt --all --check — clean
  • cargo clippy --tests — no warnings
  • cargo test --lib memory::tree — 124 passed
  • cargo test --test flavoured_tree — 1 passed
  • Full cargo test green (one pre-existing flaky queue test, drain_tolerates_retired_kind_rows, intermittently fails under full-suite parallelism and passes in isolation — unrelated to this change, which touches no queue code).

https://claude.ai/code/session_01TvyrqfH6dBqs7D6XFdSRRP

Add the ask-driven "flavoured" tree family (issue #68): a variant of the
source/topic/global bucket-seal trees whose every summarisation step is
steered by a natural-language ask.

- TreeKind::Flavoured + "flavoured" wire string; SummaryTreeKind::Flavoured
  with wiki/summaries/flavoured-<scope>/ path routing and front-matter.
- Persist the ask on mem_tree_trees via a nullable `ask` column (schema +
  add_column_if_missing migration); thread through Tree.ask, insert/row_to_tree,
  and every SELECT.
- get_or_create_tree_with_ask stamps the ask at create time.
- SummaryContext.ask, populated from the tree row at seal; prepare_summary_prompt
  emits a flavour-directed profile prompt when an ask is present.
- TreeFactory::flavoured(scope, ask) with LabelStrategy::Empty.
- TreeConfig::flavour_root_token_budget (default 1000).

Claude-Session: https://claude.ai/code/session_01TvyrqfH6dBqs7D6XFdSRRP
The deliverable for issue #68: the top of a flavoured tree compiled into a
single, small, always-fresh markdown profile a host can inject verbatim.

- compile_flavoured_root(config, tree_id): reads the root SummaryNode body,
  clamps it to flavour_root_token_budget tokens, and stages it with light
  YAML front-matter (ask, tree id, scope, sealed_at, leaves_folded evidence
  changelog, token estimate).
- Staged atomically and overwritten in place at flavoured/<scope>.md so hosts
  read a fixed path; it is a pure projection of the root node, untracked in
  SQLite.
- Recompiled after any seal that touches the root, via a hook in
  cascade_all_from_with_services (covers append_leaf, flush, force_flush/seal_now).
- Unit tests, an end-to-end integration test (tests/flavoured_tree.rs), and a
  spec page (docs/spec/flavoured-trees.md).

Claude-Session: https://claude.ai/code/session_01TvyrqfH6dBqs7D6XFdSRRP
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 44 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 53c7faad-32a6-4687-af80-86f8cbec2fe3

📥 Commits

Reviewing files that changed from the base of the PR and between 17f4cbc and 273afe4.

📒 Files selected for processing (27)
  • docs/spec/flavoured-trees.md
  • src/memory/chunks/connection.rs
  • src/memory/chunks/schema.rs
  • src/memory/chunks/store_embed_tests.rs
  • src/memory/config.rs
  • src/memory/retrieval/test_support.rs
  • src/memory/store/content/compose/summary.rs
  • src/memory/store/content/paths.rs
  • src/memory/sync/rebuild.rs
  • src/memory/tree/bucket_seal.rs
  • src/memory/tree/bucket_seal_label_tests.rs
  • src/memory/tree/direct_ingest.rs
  • src/memory/tree/factory.rs
  • src/memory/tree/factory_tests.rs
  • src/memory/tree/flavoured.rs
  • src/memory/tree/flavoured_tests.rs
  • src/memory/tree/io_tests.rs
  • src/memory/tree/mod.rs
  • src/memory/tree/read_tests.rs
  • src/memory/tree/registry.rs
  • src/memory/tree/registry_tests.rs
  • src/memory/tree/store/store_tests.rs
  • src/memory/tree/store/trees.rs
  • src/memory/tree/store/types.rs
  • src/memory/tree/summarise.rs
  • src/memory/tree/summarise_tests.rs
  • tests/flavoured_tree.rs

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 273afe4a89

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

crate::memory::tree::TreeKind::Source => SummaryTreeKind::Source,
crate::memory::tree::TreeKind::Topic => SummaryTreeKind::Topic,
crate::memory::tree::TreeKind::Global => SummaryTreeKind::Global,
crate::memory::tree::TreeKind::Flavoured => SummaryTreeKind::Flavoured,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh flavoured artifacts after direct ingest

When a flavoured tree is populated through the documented ingest_summary path, this new match arm allows the ingest to stage a flavoured L1 summary, but the function only recompiles the prompt artifact from the cascade hook. For the common under-fanout case (sealed_ids is empty after line 137), the transaction may have just set root_id to this summary, yet flavoured/<scope>.md is never written or refreshed, so hosts reading the stable compiled-root path see a missing or stale profile until enough direct-ingested summaries trigger a higher-level seal.

Useful? React with 👍 / 👎.

Comment on lines +88 to +89
let budget = config.tree.flavour_root_token_budget;
let (clamped, token_estimate) = clamp_to_budget(body.trim(), budget);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reserve front-matter space in root budget

When the root summary body is already near flavour_root_token_budget, clamping the body to the full budget and then adding YAML front-matter returns a markdown artifact that exceeds the advertised ≤1000-token compiled-root budget. This happens with ordinary sealed profiles whose body estimates at the configured budget, and gets worse for long asks, while token_estimate still reports only the body size; hosts that reserve the configured budget for the prompt-ready file can overflow their prompt allowance.

Useful? React with 👍 / 👎.

@senamakel senamakel merged commit 1a3fcc5 into main Jul 14, 2026
8 checks passed
@senamakel senamakel deleted the feat/flavoured-trees branch July 14, 2026 04:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(tree): flavoured memory trees — ask-driven distillation into a ≤1000-token root markdown artifact

1 participant